package bo;

import IBO.IIntervention;
import IBO.ITechnicien;
import IBO.IZoneGeographique;
import boerrors.TechnicienInexistantException;
import dao.AbstractFactory;
import dao.dto.AdresseDto;
import dao.dto.RoleDto;
import dao.dto.TechnicienDto;
import dao.dto.ZoneDto;
import boerrors.AdresseMinimumMultiplicityException;
import boerrors.CodePostalMinimumMultiplicityException;
import boerrors.RoleMinimumMultiplicityException;
import boerrors.TechnicienExistantException;
import boerrors.ZoneMinimumMultiplicityException;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.text.DateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Technicien extends Employe implements ITechnicien, Serializable, Cloneable{
        private Vector<Intervention> _listeInterventions = new Vector<Intervention>();
        private Zone _zone = null;
    
	//*******************************************************************
	//Constructeurs
	//*******************************************************************
        
        public Technicien(TechnicienDto tech) throws RemoteException {
                super(  tech.getMatricule(), tech.getNom(), tech.getPrenom(), tech.getTelephone(), 
                        tech.getEmail(), tech.getFonction(), tech.getPassword());
                Adresse adresse = new Adresse(tech.getAdresse());
                this.setAdresse(adresse);
                Zone zone = new Zone(tech.getZone());
                this.enregistrerZone(zone);
                Role role = new Role(tech.getRole());
                enregistrerRole(role);
                UnicastRemoteObject.exportObject(this,0);
        }
        
        public Technicien(  String nom, String prenom, Adresse adresse, 
                            String telephone, String email, Role role, 
                            String fonction, String password, Zone zone) throws RemoteException {
                super(nom, prenom, adresse, telephone, email, role, fonction, password);
                try {
                    this._zone = zone;
                    AbstractFactory.getInstance().getTechnicienDao().enregistrer(creerTechnicienDto());
                    this._listeInterventions = new Vector<Intervention>();
                    ListeTechniciens.getInstance().ajouterTechnicien(this);
                    UnicastRemoteObject.exportObject(this, 0);
                } catch (AdresseMinimumMultiplicityException ex) {
                    Logger.getLogger(Technicien.class.getName()).log(Level.SEVERE, null, ex);
                } catch (CodePostalMinimumMultiplicityException ex) {
                    Logger.getLogger(Technicien.class.getName()).log(Level.SEVERE, null, ex);
                } catch (ZoneMinimumMultiplicityException ex) {
                    Logger.getLogger(Technicien.class.getName()).log(Level.SEVERE, null, ex);
                } catch (RoleMinimumMultiplicityException ex) {
                    Logger.getLogger(Technicien.class.getName()).log(Level.SEVERE, null, ex);
                } catch (TechnicienExistantException ex) {
                    Logger.getLogger(Technicien.class.getName()).log(Level.SEVERE, null, ex);
                }
        }
        
        public Technicien(  int matricule, String nom, String prenom, Adresse adresse, 
                            String telephone, String email, Role role, String fonction, 
                            String password, Zone zone) throws RemoteException {
                super(matricule, nom, prenom, adresse, telephone, email, role, fonction, password);
                try {
                    this._zone = zone;
                    AbstractFactory.getInstance().getTechnicienDao().enregistrer(creerTechnicienDto());
                    this._listeInterventions = new Vector<Intervention>();
                    ListeTechniciens.getInstance().ajouterTechnicien(this);
                    UnicastRemoteObject.exportObject(this, 0);
                } catch (AdresseMinimumMultiplicityException ex) {
                    Logger.getLogger(Technicien.class.getName()).log(Level.SEVERE, null, ex);
                } catch (CodePostalMinimumMultiplicityException ex) {
                    Logger.getLogger(Technicien.class.getName()).log(Level.SEVERE, null, ex);
                } catch (ZoneMinimumMultiplicityException ex) {
                    Logger.getLogger(Technicien.class.getName()).log(Level.SEVERE, null, ex);
                } catch (RoleMinimumMultiplicityException ex) {
                    Logger.getLogger(Technicien.class.getName()).log(Level.SEVERE, null, ex);
                } catch (TechnicienExistantException ex) {
                    Logger.getLogger(Technicien.class.getName()).log(Level.SEVERE, null, ex);
                }
        }

        //Convertir bo - dto
        public TechnicienDto creerTechnicienDto() throws    RemoteException, RoleMinimumMultiplicityException, 
                                                            ZoneMinimumMultiplicityException, 
                                                            AdresseMinimumMultiplicityException, 
                                                            CodePostalMinimumMultiplicityException {
                AdresseDto adresse = this.getAdresse().creerAdresseDto();
                RoleDto role = this.getRole().creerRoleDto();
                ZoneDto zone = this.getZone().creerZoneDto();
                return new TechnicienDto(   this.getMatricule(), this.getNom(), this.getPrenom(), 
                                            adresse, this.getTelephone(), this.getEmail(),
                                            this.getFonction(), this.getPassword(), role, zone);
        }
        
	//*******************************************************************
	//Setters
	//*******************************************************************
        
        public synchronized void setListeInterventions(Vector<Intervention> listeIntervention) throws RemoteException {
//            this._listeInterventions = new Vector<Intervention>();
//            for (int i = 0; i < listeIntervention.size(); i++){
//                this._listeInterventions.add((Intervention)listeIntervention.get(i));
//            }
            this._listeInterventions = listeIntervention;
        }
        
        //*******************************************************************
	//Getters
	//******************************************************************* 
        
        public synchronized Vector<Intervention> getListeInterventions() throws RemoteException {
                return _listeInterventions;
        }  

        public synchronized Vector<IIntervention> getListeIInterventions() throws RemoteException {
            Vector<IIntervention> listeTampon = new Vector<IIntervention>();
                for (int i = 0; i < this._listeInterventions.size(); i++) 
                    listeTampon.add((IIntervention) this._listeInterventions.get(i));
                return listeTampon;
        }
        // liste les interventions today et les encours dépassés
        public synchronized Vector<IIntervention> getListeIInterventionsToday() throws RemoteException {
            Vector<IIntervention> listeTampon = new Vector<IIntervention>();
                for (int i = 0; i < this._listeInterventions.size(); i++){
                     Intervention intervention = this._listeInterventions.get(i);
                     DateFormat date1 = DateFormat.getDateInstance();
                     String d1 = date1.format(intervention.getDateIntervention().getTime());
                     DateFormat date2 = DateFormat.getDateInstance();
                     String d2 = date2.format(new Date());
                     if(d1.compareTo(d2)==0 ||(d1.compareTo(d2)<0 && intervention.getIStatut().compareTo("EN")==0))
                         listeTampon.add((IIntervention) intervention);
                }
                return listeTampon;
        }
        
        public synchronized Zone getZone() throws RemoteException, ZoneMinimumMultiplicityException {
                if (! aUneZoneValide()) throw new ZoneMinimumMultiplicityException();
		return _zone;
        }
        
        public synchronized IZoneGeographique getIZone() throws RemoteException, ZoneMinimumMultiplicityException {
                if (! aUneZoneValide()) throw new ZoneMinimumMultiplicityException();
		return (IZoneGeographique)_zone;
        }
        
        //*******************************************************************
	//Associations -> Intervention
	//*******************************************************************
        
        public synchronized boolean ajouterIntervention(Intervention intervention){
                if (intervention == null) return false;
                if (this.contientIntervention(intervention)) return false;
                if (!this.peutAjouterIntervention()) return false;
                /*try {
                        if (!intervention.peutEnregistrerClient() && intervention.getTechnicien() != this)
                        return false;
                } catch (MinimumMultiplicityException e) {throw new InternalError();}*/
                _listeInterventions.add(intervention);
                intervention.enregistrerTechnicien(this);
                return true;
        }

        public synchronized boolean supprimerIntervention(Intervention intervention) {
                if (intervention == null) return false;
                //Test à faire en fonction du statut de l'intervention
                //Exemple : on ne peut pas supprimer le technicien d'une intervention clôturée
                if (! this.contientIntervention(intervention)) return false;
                _listeInterventions.remove(intervention);
                intervention.supprimerTechnicien();
                return true;
        }

        public boolean contientIntervention(Intervention intervention) {
                return _listeInterventions.contains(intervention);
        }

        public Iterator<Intervention> interventions() /*throws MinimumMultiplicityException*/  {
                //if (! aAssezInterventions()) throw new MinimumMultiplicityException();
                return _listeInterventions.iterator();
        }

        public int nombreInterventions() /*throws MinimumMultiplicityException*/  {
                //if (! aAssezDeCommandes()) throw new MinimumMultiplicityException();
                return _listeInterventions.size();
        }
        
        public boolean peutAjouterIntervention(){
                return true;
        }
    
        public boolean aAssezInterventions() {
                return true;
	}
    
	//*******************************************************************
	//Associations -> Zone
	//*******************************************************************
        
        public synchronized boolean enregistrerZoneClone(Zone zone) {
                if (zone==null) return false;
                if (this._zone == zone) return false;
		this._zone = zone;
		return true;
	}

        public synchronized boolean enregistrerZone(Zone zone) {
                if (zone==null) return false;
                if (this._zone == zone) return false;
		if (! peutEnregistrerZone()) return false;
		this._zone = zone;
		return true;
	}

        //Aucune suppression de la zone n'est autorisée

        private synchronized boolean peutEnregistrerZone() {
                return this._zone == null;
	}
        
        public synchronized boolean aUneZoneValide() {
                return this._zone != null;
        }   
        
	//*******************************************************************
	//Methodes static
	//*******************************************************************
        
        public synchronized static Vector<Technicien> lister() throws RemoteException, TechnicienInexistantException {
                Vector<TechnicienDto> listeTechnicienDto = AbstractFactory.getInstance().getTechnicienDao().lister();
                Vector<Technicien> listeTechnicien = new Vector<Technicien>();
                for (int i = 0 ; i < listeTechnicienDto.size() ; i++){
                    TechnicienDto tech = listeTechnicienDto.get(i);
                    listeTechnicien.add(new Technicien(tech));
                }
                return listeTechnicien;
        }
        
        public synchronized static void modifier(Technicien technicien) throws  RemoteException, 
                                                                                TechnicienInexistantException, 
                                                                                RoleMinimumMultiplicityException, 
                                                                                ZoneMinimumMultiplicityException, 
                                                                                AdresseMinimumMultiplicityException, 
                                                                                CodePostalMinimumMultiplicityException {
                AbstractFactory.getInstance().getTechnicienDao().modifier(technicien.creerTechnicienDto());
        }
        
        //*******************************************************************
	//Method Clonable
	//*******************************************************************        
        
        @Override
        public Object clone(){
            // On récupère l'instance à renvoyer par l'appel de la 
	    // méthode super.clone() (ici : Personne.clone())
             Technicien technicien = (Technicien) super.clone();
            // on renvoie le clone
            return technicien;
        }        
}